package com.macrounion.atv.processor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.macrounion.atv.cache.CurrentDataCache;
import com.macrounion.atv.cache.DeviceIdQueue;
import com.macrounion.atv.listener.DataReceiveListener;
import com.macrounion.atv.service.entity.CurrentData;
import com.macrounion.atv.service.service.CurrentDataService;
import com.macrounion.base.processor.BaseProcessor;
import com.macrounion.base.service.utils.DateUtils;

@Component
@Transactional
public class SaveCurrentDataProcessor extends BaseProcessor<CurrentData, CurrentData, CurrentDataService, CurrentData> {

    @Autowired
    private CurrentDataCache currentDataCache;
    
    @Autowired
    private DeviceIdQueue deviceIdQueue;
    
    @Value("${timely.saveStep:5}")
    private int savetime;

    private static Logger logger = LoggerFactory.getLogger(SaveCurrentDataProcessor.class);
    /**
     * 存储来自snmpGet的实时数据
     *
     * @param datas
     */
    @Transactional
    @CachePut(value = "currentdatas", key = "#deviceId")
    public List<CurrentData> saveData(String deviceId, List<CurrentData> cdatas,String type) {
//    	List<CurrentData> cdatas = new ArrayList<>(datas);
    	synchronized(deviceId.intern()) {
            List<CurrentData> full = new ArrayList<CurrentData>(currentDataCache.getCurrentData(deviceId));
    		if (CollectionUtils.isEmpty(cdatas)) {
                return full;
            }
//    		System.out.println(deviceId+"-当前数量-"+full.size());
    		try {
                cdatas =cansave(cdatas, full);
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
            if (CollectionUtils.isEmpty(full))
                full = Lists.newArrayList();
            deviceIdQueue.take(deviceId+"-"+type);
            return getFull(full, cdatas);
    	}
    }

    /**
     * 删选过5分钟更新的数据（更新数据库最快5分钟一次）
     *
     * @param datas
     * @param olds
     * @return
     */
    private List<CurrentData> cansave(List<CurrentData> datas, List<CurrentData> olds) {
    	List<CurrentData> saves = Lists.newArrayList();
    	datas.parallelStream().forEach(n->{
    		CurrentData o = olds.parallelStream().filter(old -> {
                return old.getChannelCode().equals(n.getChannelCode());
            }).findFirst().orElse(null);
    		if (o == null)
    			saves.add(n);
    		else {
    			 if (o.getUpdateTime() == null) {
	                n.setUpdateTime(new Date());
	                saves.add(n);
	             }else {
	            	 boolean r = DateUtils.addMinute(o.getUpdateTime(), savetime).before(n.getCreatedTime());
//    	             System.out.println(r);
//	    	            boolean r = DateUtils.addSecond(o.getUpdateTime(), 20).before(n.getCreatedTime());
    	             if (!r)
    	                n.setUpdateTime(o.getUpdateTime());
    	             else {
    	                n.setUpdateTime(new Date());
    	                saves.add(n);
    	             }
	             }
    		}
    	});
    	saves.removeIf(r->{return r==null;});
    	if(!CollectionUtils.isEmpty(saves))
    		this.service.saveData(saves);
    	return datas;
    }

    /**
     * 保持缓存数据完整性，部分数据更新，虚拟通道持久化
     *
     * @param full
     * @param datas
     * @return
     */
    private List<CurrentData> getFull(List<CurrentData> full, List<CurrentData> datas) {
//    	if(CollectionUtils.isEmpty(datas))
//    		datas = Lists.newArrayList();
    	Collection<CurrentData> cs = full.parallelStream().filter(data->{return datas.parallelStream().anyMatch(f->{return f.getChannelCode().equals(data.getChannelCode());});}).collect(Collectors.toSet());
        full.removeAll(cs);
    	datas.forEach(data -> {
             full.add(data);
             try {
            	 currentDataCache.saveCurrentdatadetails(data);
//            	 CurrentData c = currentDataCache.getCurrentdatadetails(data.getDeviceCode(), data.getChannelCode());
//            	 System.out.println(c.getChannelCode()+"->"+c.getShowValue());
			 } catch (Exception e) {
				 e.printStackTrace();
				 logger.error("存储明细失败"+data.getDeviceCode()+"-"+data.getChannelCode());
				 currentDataCache.removeCurrentdatadetails(data.getDeviceCode(), data.getChannelCode());
			 }
        });
        return full;
    }
  
}